package com.ebo.learn_demo.view

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import androidx.annotation.IntRange


/**
 * @author zmp
 * @date : 2021/12/20 16:28
 * des:NewGuideView
 */
class NewGuideView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    private var TAG = "NewGuideView"
    private val mTextPaint = TextPaint()
    private val mDrawList = mutableListOf<DrawTipsInfo>()

    private val mPath = Path()
    private var mTips: MutableList<TipsInfo>? = null

    fun setGuideTips(tips: MutableList<TipsInfo>?): NewGuideView {
        mTips = tips
        mPath.reset()
        mDrawList.clear()
        mTips?.map { tipsInfo ->
            val rectF = RectF(
                tipsInfo.view.left.toFloat(),
                tipsInfo.view.top.toFloat(),
                tipsInfo.view.right.toFloat(),
                tipsInfo.view.bottom.toFloat()
            )
            mPath.addRect(
                rectF,
                Path.Direction.CW
            )
            var layoutW = width / 2
            if (tipsInfo.maxWith > 0) {
                layoutW = tipsInfo.maxWith
            }
            val myStaticLayout = StaticLayout(
                tipsInfo.tipsMsg,
                mTextPaint,
                layoutW,
                Layout.Alignment.ALIGN_NORMAL,
                1.0f,
                0.0f,
                false
            )
            if (rectF.width() <= 0 || rectF.height() <= 0) {
                return@map
            }
            mDrawList.add(DrawTipsInfo(rectF, myStaticLayout, tipsInfo.gravity))
        }
        invalidate()
        return this
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        setGuideTips(mTips)
    }


    @SuppressLint("DrawAllocation")
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.save()
        canvas.clipPath(mPath, Region.Op.DIFFERENCE)
        canvas.drawColor(Color.parseColor("#33000000"))
        canvas.restore()
        mDrawList.forEach {
            when (it.gravity) {
                0 -> { //left
                    val lineEnd = it.tipsLayout.getLineWidth(0)
                    val height = it.tipsLayout.height
                    canvas.save()
                    canvas.translate(it.rectF.left - lineEnd, it.rectF.centerY() - height / 2)
                    it.tipsLayout.draw(canvas)
                    canvas.restore()
                }
                1 -> {//top
                    val lineEnd = it.tipsLayout.getLineWidth(0)
                    val height = it.tipsLayout.height
                    canvas.save()
                    canvas.translate(it.rectF.centerX() - lineEnd / 2, it.rectF.top - height)
                    it.tipsLayout.draw(canvas)
                    canvas.restore()
                }
                2 -> {//right
                    val lineEnd = it.tipsLayout.getLineWidth(0)
                    val height = it.tipsLayout.height
                    canvas.save()
                    canvas.translate(it.rectF.right, it.rectF.centerY() - height / 2)
                    it.tipsLayout.draw(canvas)
                    canvas.restore()
                }
                3 -> { //bottom
                    val lineEnd = it.tipsLayout.getLineWidth(0)
                    val height = it.tipsLayout.height
                    canvas.save()
                    canvas.translate(
                        it.rectF.centerX() - lineEnd / 2,
                        it.rectF.bottom
                    )
                    it.tipsLayout.draw(canvas)
                    canvas.restore()
                }
                else -> {
                    val lineEnd = it.tipsLayout.getLineWidth(0)
                    canvas.save()
                    canvas.translate(it.rectF.centerX() - lineEnd, it.rectF.bottom)
                    canvas.rotate(-45F, lineEnd, 0F)
                    it.tipsLayout.draw(canvas)
                    canvas.restore()
                }
            }
        }
    }

    private val mTextSize by lazy {
        40f
    }

    init {
        mTextPaint.color = Color.WHITE
        mTextPaint.style = Paint.Style.FILL
        mTextPaint.textSize = mTextSize
    }
}


fun NewGuideView.show(parent: ViewGroup) {
    translationZ = 10F
    parent.addView(
        this,
        ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
    )
}

data class TipsInfo(
    val view: View,
    val tipsMsg: String,
    @IntRange(from = -1, to = 3) var gravity: Int = -1,
    val maxWith: Int = -1
)

data class DrawTipsInfo(
    val rectF: RectF,
    val tipsLayout: StaticLayout,
    @IntRange(from = -1, to = 3) var gravity: Int = -1,
)